package com.ophiux.wechat.utils;

import java.security.MessageDigest;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ophiux.wechat.executor.CM_OrderQueryExecutor;
import com.ophiux.wechat.executor.Native_UnifiedOrderExecutor;
import com.ophiux.wechat.executor.OauthExecutor;
import com.ophiux.wechat.executor.SP_OrderQueryExecutor;
import com.ophiux.wechat.executor.UnifiedOrderExecutor;
import com.ophiux.wechat.executor.WXReFundExecutor;
import com.ophiux.wechat.model.CM_OrderQueryRequest;
import com.ophiux.wechat.model.CM_OrderQueryResponse;
import com.ophiux.wechat.model.CM_ReFundRequest;
import com.ophiux.wechat.model.CM_UnifiedOrderRequest;
import com.ophiux.wechat.model.OauthRequest;
import com.ophiux.wechat.model.PayJsModel;
import com.ophiux.wechat.model.SP_OrderQueryRequest;
import com.ophiux.wechat.model.SP_OrderQueryResponse;
import com.ophiux.wechat.model.SP_UnifiedOrderRequest;
import com.ophiux.wechat.model.UnifiedOrderResponse;

/**
 * 微信支付统一工具类
 * @author chenh
 * 2016-11-15
 *
 */
public class WeChatPayUtil {

	private static Logger logger = LoggerFactory.getLogger(WeChatPayUtil.class);
	
	/**
	 * 我方签名失败
	 */
	private static String SIGN_ERROR = "500";
	 /**
	  * 
	  * @param appid   公众号ID
	  * @param appsecrest  公众号秘钥
	  * @param mch_id  商户号或子商户号
	  * @param out_trade_no
	  * @param op_user_id
	  * @param out_refund_no
	  * @param refund_fee
	  * @param total_fee
	  * @param sign
	  */
	public static String ReFund(String appid,String api_key,String appsecrest,String mch_id,
			String out_trade_no,String op_user_id,String out_refund_no,
			String refund_fee,String total_fee,String sign,String sslFilePath){
		
		/**
		 * 存放退款结果
		 */
		String message = "";
		/**
		 * 判断商户信息是否存在
		 */
		if(StringUtil.isEmpty(appid)||StringUtil.isEmpty(api_key)
				||StringUtil.isEmpty(appsecrest)){
			
			message = ResponseDealUtil.toRefundErrorMessage("500", "商户信息错误或不存在！");
			return message;
		}
		
		/**
		 * keys:subMchId,outTradeNo,opUserId,outRefundNo,refundFee,totalFee,appid,appsecret
		 * values:传入参数
		 */
		 try {
			String []keys = new String[]{"subMchId","outTradeNo","opUserId",
					"outRefundNo","refundFee","totalFee","appid","appsecret"};
			String []values = new String[]{mch_id,out_trade_no,op_user_id,out_refund_no,
											refund_fee,total_fee,appid,appsecrest};
			SortedMap<String, String> packageParams = new TreeMap<String, String>();
			packageParams = MapBuilder.getInstance()
					.buildSortMap(keys, values);
			
		
	
			if(sign.equals(WeChatSignUtil.getInstance("")
					.createSHA1Sign(packageParams))){
				/**
				 * 和终端传入的签名进行对比
				 */
				CM_ReFundRequest refundReq = new CM_ReFundRequest();
				refundReq.setAppid(appid);
				refundReq.setMch_id(mch_id);
				refundReq.setOp_user_id(op_user_id);
				refundReq.setOut_refund_no(out_refund_no);
				refundReq.setRefund_fee(refund_fee);
				refundReq.setTotal_fee(total_fee);
				refundReq.setOut_trade_no(out_trade_no);
				
				/**
				 * 参数准备完毕，执行退款操作
				 */
				String refund_response= new WXReFundExecutor(refundReq,api_key,sslFilePath).execute();
				logger.info("普通商户:"+appid+"(公众号ID)"+mch_id+"(商户号)"
						+"-商户订单号:"+out_trade_no+"退款单号"+out_refund_no
						+"-退款返回结果:"+refund_response);
				 
				message = refund_response;
				
			 }else{
				System.out.println("mch_id="+mch_id);
				System.out.println("outTradeNo="+out_trade_no);
				System.out.println("opUserId="+op_user_id);
				System.out.println("outRefundNo="+out_refund_no);
				System.out.println("refundFee="+refund_fee);
				System.out.println("totalFee="+total_fee);
				System.out.println("原sign="+sign);
				System.out.println("新Sign="+WeChatSignUtil.getInstance("")
						.createSHA1Sign(packageParams));
				System.out.println("签名错误!");
				logger.info("sign="+sign);
				logger.info("Sign="+WeChatSignUtil.getInstance("")
						.createSHA1Sign(packageParams));
				logger.info("签名错误!");
				
				message = ResponseDealUtil.toRefundErrorMessage(SIGN_ERROR, "签名错误！");
					 
				}
			} catch (Exception e) {
				logger.error("普通商户:"+appid+"(公众号ID)"+mch_id+"(商户号)"
						+"--申请退款异常信息：{}",new String []{e.toString()});
				e.printStackTrace();
				message = ResponseDealUtil.toRefundErrorMessage(SIGN_ERROR, "系统异常");
			}
		return message;
	}
	
 
	/**
	 * 普通商户统一下单
	 * @param cm_unifiedOrderRequest
	 * @return
	 */
	public static UnifiedOrderResponse UnifiedOrder(CM_UnifiedOrderRequest cm_unifiedOrderRequest,String api_key){
		
		UnifiedOrderResponse unifiedOrderResponse = null;
		try {
			
		  unifiedOrderResponse = 
				new UnifiedOrderExecutor(cm_unifiedOrderRequest,api_key).execute();
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
			logger.info("统一下单执行异常");
		}
		
		return unifiedOrderResponse;
		
	}
	
 
	
	public static String  Oauth(String appid,String appsecret,String code){
		
		/**
		 * 验证公众号信息是否正确
		 */
		if(StringUtil.isEmpty(appid)||StringUtil.isEmpty(appsecret)){
			return "";
		}
		
		OauthRequest oauth = new OauthRequest();
		oauth.setAppid(appid);
		oauth.setAppsecret(appsecret);
		oauth.setCode(code);
		
		String openId = "";
		
		try {
			
			openId = new OauthExecutor(oauth).execute();
			
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
			logger.info("微信授权异常-授权参数："+oauth.toString());
		}
		logger.info("微信授权结果："+openId);
		
		return openId;
		
	}
	
	
	/**
	 * 生成支付对象
	 * 即构造js调起微信支付所需要的参数
	 * @author chenh
	 * 2016-11-22
	 */
	public static PayJsModel toPayJsParam(String appid,String prepay_id,String api_key){
		
		String packages = "prepay_id="+prepay_id;
		String timeStamp = CommonUtil.getTimeStamp();
		String nonceStr = CommonUtil.getNonceStr();
		
		
		String []keys = new String []{"appId","timeStamp","nonceStr","package","signType"};
		String []values = new String []{appid,timeStamp,nonceStr,packages,"MD5"};
		
		SortedMap<String, String> finalpackage = new TreeMap<String, String>();
		finalpackage = MapBuilder.getInstance().buildSortMap(keys, values);
		
		String sign = WeChatSignUtil.getInstance(api_key).createSign(finalpackage);
		
		/**
		 * 生成支付对象
		 */
		PayJsModel pay = new PayJsModel();
		//要签名
		pay.setAppId(appid);
		pay.setNonceStr(nonceStr);
		pay.setPackages(packages);
		pay.setTimeStamp(timeStamp);
		pay.setPaySign(sign);
		pay.setSignType("MD5");
		
		return pay;
	}
	
	
	/**
	 * 查询微信支付订单
	 * 注释：调用方调用该方法获取订单后，需要对订单进行判空操作
	 * @param appid  微信公众号ID
	 * @param mch_id  商户号
	 * @param out_trade_no  商家订单号，商家订单唯一标识
	 * @param api_key  商户平台api安全秘钥
	 * @author chenh
	 * 2016-11-23
	 */
	private static String SIGN_TYPE = "MD5";
	
	public static CM_OrderQueryResponse OrderQuery(String appid,String mch_id,String out_trade_no,String api_key){
		
		CM_OrderQueryRequest orderQueryReq = new CM_OrderQueryRequest();
		orderQueryReq.setAppid(appid);
		orderQueryReq.setMch_id(mch_id);
		
		String nonce_str = CommonUtil.getNonceStr();
		orderQueryReq.setNonce_str(nonce_str);
		
		orderQueryReq.setOut_trade_no(out_trade_no);
		
		SortedMap<String, String> packageParams = new TreeMap<String, String>();
		String [] keys = new String[]{"appid","mch_id","nonce_str","out_trade_no"};
		String []values = new String[]{appid,mch_id,nonce_str,out_trade_no};
		
		packageParams = MapBuilder.buildSortMap(keys, values);
		
		/**
		 * 生成签名
		 */
		String sign = WeChatSignUtil.getInstance(api_key).createSign(packageParams);
		
		orderQueryReq.setSign(sign);
		orderQueryReq.setSign_type(SIGN_TYPE);
		
		/**
		 * 开启执行器
		 */
		CM_OrderQueryResponse order = null;
		try {
			order = new CM_OrderQueryExecutor(orderQueryReq).execute();
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
			logger.info(out_trade_no+"微信查询订单失败-异常");
		}
		
		return order;
	}
	 
	/**
	 * 
	 * @param sp_order_query_request   普通商户-微信支付订单查询
	 * @param api_key  api安全秘钥          商户平台-安全设置-api安全
	 * @return
	 */
	public static CM_OrderQueryResponse OrderQuery(CM_OrderQueryRequest cm_order_query_request,String api_key){
		
		String appid = cm_order_query_request.getAppid();
		String mch_id = cm_order_query_request.getMch_id();
		String out_trade_no = cm_order_query_request.getOut_trade_no();
		String transaction_id = cm_order_query_request.getTransaction_id();
		
		String nonce_str = cm_order_query_request.getNonce_str();
		
		/**
		 * 设置随机字符串
		 */
		if(StringUtil.isEmpty(nonce_str)){
		    nonce_str = CommonUtil.getNonceStr();
			cm_order_query_request.setNonce_str(nonce_str);
		}
		
		SortedMap<String, String> packageParams = new TreeMap<String, String>();
		String [] keys = new String[]{"appid","mch_id","nonce_str","out_trade_no"};
		String []values = new String[]{appid,mch_id,nonce_str,out_trade_no};
		
		packageParams = MapBuilder.buildSortMap(keys, values);
		
		/**
		 * 生成签名
		 */
		String sign = WeChatSignUtil.getInstance(api_key).createSign(packageParams);
		
		cm_order_query_request.setSign(sign);
		cm_order_query_request.setSign_type(SIGN_TYPE);
		
		/**
		 * 开启执行器
		 */
		CM_OrderQueryResponse order = null;
		try {
			order = new CM_OrderQueryExecutor(cm_order_query_request).execute();
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
			logger.info(out_trade_no+"普通商户-微信查询订单失败-异常");
		}
		
		return order;
	}
	
	/**
	 * 
	 * @param sp_order_query_request   服务商-微信支付订单查询
	 * @param api_key  api安全秘钥          商户平台-安全设置-api安全
	 * @return
	 * 2016-12-16
	 * 
	 * 待做项提醒
	 * 1.签名处待优化，根据键值对非空进行组合       ---2016-12-16  chenh记录
	 * 
	 */
	public static SP_OrderQueryResponse OrderQuery(SP_OrderQueryRequest sp_order_query_request,String api_key){
		
		String appid = sp_order_query_request.getAppid();
		String mch_id = sp_order_query_request.getMch_id();
		String sub_mch_id = sp_order_query_request.getSub_mch_id();
		String out_trade_no = sp_order_query_request.getOut_trade_no();
		String transaction_id = sp_order_query_request.getTransaction_id();
		
		String nonce_str = sp_order_query_request.getNonce_str();
		
		/**
		 * 设置随机字符串
		 */
		if(StringUtil.isEmpty(nonce_str)){
		    nonce_str = CommonUtil.getNonceStr();
		    sp_order_query_request.setNonce_str(nonce_str);
		}
		
		SortedMap<String, String> packageParams = new TreeMap<String, String>();
		String [] keys = new String[]{"appid","mch_id","nonce_str","out_trade_no","sub_mch_id"};
		String []values = new String[]{appid,mch_id,nonce_str,out_trade_no,sub_mch_id};
		
		packageParams = MapBuilder.buildSortMap(keys, values);
		
		/**
		 * 生成签名
		 */
		String sign = WeChatSignUtil.getInstance(api_key).createSign(packageParams);
		
		sp_order_query_request.setSign(sign);
		sp_order_query_request.setSign_type(SIGN_TYPE);
		
		/**
		 * 开启执行器
		 */
		SP_OrderQueryResponse order = null;
		try {
			order = new SP_OrderQueryExecutor(sp_order_query_request).execute();
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
			logger.info(out_trade_no+"服务商-微信查询订单失败-异常");
		}
		
		return order;
	}
	
	
	/**
	 * 
	 * @param appid  微信公众号ID
	 * @param mch_id  商户号
	 * @param out_trade_no  商家订单号，商家订单唯一标识
	 * @param api_key  商户平台api安全秘钥
	 * @return
	 */
	public static String OrderQueryAsString(String appid,String mch_id,String out_trade_no,String api_key){
		
		CM_OrderQueryResponse order = OrderQuery(appid, mch_id, out_trade_no, api_key);
		
		ObjectMapper obj=new ObjectMapper();
		String orderStr = "";
		try {
			 orderStr = obj.writeValueAsString(order);
		} catch (JsonProcessingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			logger.info(out_trade_no+"微信查询订单失败-异常");
		}
		return orderStr;
	}
	
	
	public static UnifiedOrderResponse Native_UnifiedOrder(SP_UnifiedOrderRequest sp_unifiedOrderRequest,String api_key){
		
		UnifiedOrderResponse unifiedOrderResponse = null;
		try {
			
		  unifiedOrderResponse = 
				new Native_UnifiedOrderExecutor(sp_unifiedOrderRequest,api_key).execute();
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
			logger.info("统一下单执行异常");
		}
		
		return unifiedOrderResponse;
		
	}
	
	
	/**
	 * 9001201611192020011
	 * @param args
	 */
	public static void main(String[] args) {
	
		String appid ="wx3ff0f332cdd706ba";
		String mch_id = "1405886102";
		String out_trade_no = "920180104130903517966";
		String api_key = "cqsdjrmyyXXK2018CWK010cqsdjrmyy";
		WeChatPayUtil.OrderQueryAsString(appid, mch_id, out_trade_no, api_key);
		 
	}
	
	
	
	
	 
}
